import { SubjectComponent } from "../../../../core/subject";
import ShaderHSB from "./shader_hsb";

const { ccclass, property } = cc._decorator;

@ccclass
export default class ColorPicker extends SubjectComponent {
    @property(cc.Node)
    hueNode: cc.Node = null;

    @property(cc.Node)
    hsbNode: cc.Node = null;

    @property(cc.Node)
    hueMark: cc.Node = null;
    @property(cc.Node)
    hsbMark: cc.Node = null;

    @property(cc.Node)
    colorPad: cc.Node = null;

    hVal = 0;
    sVal = 0;
    bVal = 1;
    onDestroy() {
        let color = new cc.Color();
        color.fromHSV(this.hVal, this.sVal, this.bVal);
        this.emit("destroy", color);
    }
    onLoad() {
        this.hueNode.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.hueNode.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.hueNode.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.hueNode.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);

        this.hsbNode.on(cc.Node.EventType.TOUCH_START, this.onTouchHsbStart, this);
        this.hsbNode.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchHsbMove, this);
        this.hsbNode.on(cc.Node.EventType.TOUCH_END, this.onTouchHsbEnd, this);
        this.hsbNode.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchHsbEnd, this);
    }

    setColor(clr: cc.Color) {
        let hsv = clr.toHSV();
        this.hVal = hsv.h;
        this.sVal = hsv.s;
        this.bVal = hsv.v;

        this.hueMark.x = this.hVal * this.hueNode.width - this.hueNode.width / 2;
        this.hsbMark.x = this.sVal * this.hsbNode.width - this.hsbNode.width / 2;
        this.hsbMark.y = this.bVal * this.hsbNode.height - this.hsbNode.height / 2;

        this.hsbNode.getComponent(ShaderHSB).hVal = this.hVal;

        this.onColorChanged();
    }

    onTouchStart(evt: cc.Event.EventTouch) {
        let loc = evt.getLocation();
        this.changeHue(loc);
    }
    onTouchMove(evt: cc.Event.EventTouch) {
        let loc = evt.getLocation();
        this.changeHue(loc);
    }
    onTouchEnd(evt: cc.Event.EventTouch) {
        let loc = evt.getLocation();
        this.changeHue(loc);
    }

    onTouchHsbStart(evt: cc.Event.EventTouch) {
        let loc = evt.getLocation();
        this.changeSB(loc);
    }
    onTouchHsbMove(evt: cc.Event.EventTouch) {
        let loc = evt.getLocation();
        this.changeSB(loc);
    }
    onTouchHsbEnd(evt: cc.Event.EventTouch) {
        let loc = evt.getLocation();
        this.changeSB(loc);
    }

    changeSB(loc: cc.Vec2) {
        let np = this.hsbNode.convertToNodeSpaceAR(loc);
        if (np.x < -this.hsbNode.width / 2) {
            np.x = -this.hsbNode.width / 2;
        }
        else if (np.x > this.hsbNode.width / 2) {
            np.x = this.hsbNode.width / 2;
        }

        if (np.y < -this.hsbNode.height / 2) {
            np.y = -this.hsbNode.height / 2;
        }
        else if (np.y > this.hsbNode.height / 2) {
            np.y = this.hsbNode.height / 2;
        }

        this.sVal = (np.x + this.hsbNode.width / 2) / this.hsbNode.width;
        this.bVal = (np.y + this.hsbNode.height / 2) / this.hsbNode.height;
        // console.log("h:", this.hVal, "s:", this.sVal, "b:", this.bVal);

        this.hsbMark.setPosition(np);

        this.onColorChanged();
    }

    changeHue(loc: cc.Vec2) {
        let np = this.hueNode.convertToNodeSpaceAR(loc);
        if (np.x < -this.hueNode.width / 2) {
            np.x = -this.hueNode.width / 2;
        }
        else if (np.x > this.hueNode.width / 2) {
            np.x = this.hueNode.width / 2;
        }
        this.hueMark.x = np.x;

        this.hVal = (np.x + this.hueNode.width / 2) / this.hueNode.width;
        // console.log("h:", this.hVal);

        this.hsbNode.getComponent(ShaderHSB).hVal = this.hVal;

        this.onColorChanged();
    }

    onColorChanged() {
        let color = new cc.Color();
        color.fromHSV(this.hVal, this.sVal, this.bVal);
        this.colorPad.color = color;

        this.emit("color-changed", color);
    }

    onClickClose() {
        this.node.destroy();
    }
};